home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Hacks
/
Hacks ’95
/
Venus
/
SimpleWindow.cc
< prev
next >
Wrap
Text File
|
1995-06-23
|
9KB
|
332 lines
/*
***********************************************************************
*
*
* Simple Window Class
*
*
***********************************************************************
*/
#include "std.h"
#include "image.h"
#include "window.h"
#include <PictUtil.h>
/*
*----------------------------------------------------------------------
* Service functions
*/
// Getting a bounding rectangle of an image
ScreenRect::ScreenRect(const IMAGE& image)
{
top = 0;
bottom = top + image.q_nrows();
left = 0;
right = left + image.q_ncols();
}
// Create a rectangle of given height/width
// positioned at the origin
ScreenRect::ScreenRect(const rowcol& heightwidth)
{
left = top = 0;
bottom = heightwidth.row();
right = heightwidth.col();
}
// Create a rectangle of given height/width
// positioned at a given point
ScreenRect::ScreenRect(const rowcol& origin, const rowcol& heightwidth)
{
top = origin.row();
left = origin.col();
bottom = top+heightwidth.row();
right = left+heightwidth.col();
}
// Shifting a rectangle by the same amount
// in X and Y
ScreenRect& ScreenRect::operator += (const int offset)
{
top += offset; bottom += offset; left += offset; right += offset;
return *this;
}
// Print what rectangle is this
void ScreenRect::print(const char * title) const
{
message("Rectangle %s (%d,%d) - (%d,%d)",title,top,left,bottom,right);
}
// Used to "implicitly" convert from C to Pascal
// string
Pstr::Pstr(const char * c_str)
{
strncpy((char *)pas_string,c_str,sizeof(*this)-2);
CtoPstr((char *)pas_string);
}
/*
*----------------------------------------------------------------------
* A generic simple window that can be dragged around the screen
* and closed by clicking a "go-away" button
* No other events are handled, redefine the event handler if necessary.
*/
// Create a color window of the specified size and title
// Note, the upper left corner of 'rect' must
// NOT be (0,0)!
ScreenWindow::ScreenWindow(ScreenRect rect, const char * title)
{
const int window_offset = 100; // Cannot be 0 or small!
this_window = NewCWindow(nil,rect += window_offset,(Pstr)title,
TRUE,noGrowDocProc,
(WindowPtr)(-1),TRUE,(long)this);
assert( this_window != 0 );
SetPort(this_window);
SelectWindow(this_window);
}
// Create a color window from a resource template
ScreenWindow::ScreenWindow(const short resource_id)
{
this_window = GetNewCWindow(resource_id,nil,(WindowPtr)(-1));
SetWRefCon(this_window,(long)this);
assert( this_window != 0 );
SetPort(this_window);
SelectWindow(this_window);
}
// Close the window and clean up the rubble
ScreenWindow::~ScreenWindow(void)
{
assert( this_window != 0 );
DisposeWindow(this_window);
this_window = 0;
}
// Event handling loop. Returns only when the
// window is to be destroyed
void ScreenWindow::handle(void)
{
const long event_timeout = 1;
EventRecord theEvent;
unsigned long int prev_tick_count = 0;
for(;;)
{
if( !WaitNextEvent(everyEvent, &theEvent,event_timeout,nil) )
if( handle_null_event(theEvent.when) )
continue;
else
return;
switch (theEvent.what)
{
case mouseDown:
if( !handle_mouse_down(theEvent) )
return; // Window is to be closed (go-away buttin clicked)
break;
case updateEvt:
if( this_window == (WindowPtr)theEvent.message )
update();
break;
case keyDown:
case autoKey:
if( !handle_key_down(theEvent) )
return; // a "quit" key must've been pressed
break;
case activateEvt:
if( this_window == (WindowPtr)theEvent.message )
activate(theEvent.modifiers & 0x01);
break;
}
}
}
// Handle "mouse-down" events
// Returns FALSE if the user clicked within the
// go-away region of our window. Otherwise,
// returns TRUE
// Handles dragging if necessary and system clicks
Boolean ScreenWindow::handle_mouse_down(const EventRecord& the_event)
{
WindowPtr wp;
short windowPart = FindWindow (the_event.where, &wp);
switch (windowPart)
{
case inSysWindow:
SystemClick(&the_event, wp);
break;
case inMenuBar:
break;
case inContent:
break;
case inDrag:
if (wp == this_window )
drag(the_event.where);
break;
case inGoAway:
return FALSE;
}
return TRUE;
}
// Handles key_down & auto_key events. Return FALSE
// if the window is to be closed down
Boolean ScreenWindow::handle_key_down(const EventRecord& the_event)
{
return FALSE; // Each key kills the application, sorry
}
// Handles null events, when nothing happens for some
// time. Return FALSE when it's time to die
Boolean ScreenWindow::handle_null_event(const long event_time)
{
return TRUE; // Keep going
}
// Private window parts
// Handle an update event - redraw the window
// A virtual function draw() is called to do
// the actual redrawing
void ScreenWindow::update(void)
{
GrafPtr savePort;
GetPort(&savePort);
SetPort(this_window);
BeginUpdate(this_window);
draw();
EndUpdate(this_window);
SetPort(savePort);
}
// Make the entire window being redrawn
void ScreenWindow::refresh(void)
{
// EraseRect(&this_window->portRect);
InvalRect(&this_window->portRect);
}
// Handle an activate or deactivate event
void ScreenWindow::activate (const Boolean go_active)
{
if (go_active)
SetPort(this_window);
}
/*
*----------------------------------------------------------------------
* A simple window with an offscreen window buffer
*/
// Allocate the buffer for the offscreen
// drawing and load CLUT (if clut_id != 0)
OffScreenWindow::OffScreenWindow
(ScreenRect rect, const char * title, const short clut_id)
: ScreenWindow(rect,title), graf_world(nil)
{
CTabHandle clut_handle = nil;
if( clut_id != 0 )
{ // try to get a user CLUT with that resource id
clut_handle = GetCTable(clut_id);
assert( clut_handle != 0 );
SetWinColor(our_window(),(WinCTab**)clut_handle);
}
do_well( NewGWorld(&graf_world,8,rect,clut_handle,nil,0) );
assert( graf_world != (void *)0 );
// if( clut_handle != nil )
// DisposCTable(clut_handle); // CLUT has been copied, and can be disposed of now
// But careful! CLUT is associated with the window
// by SetWinColor(), so we don't dispose of it
// Get hold of the offscreen pixmap
pixmap = GetGWorldPixMap(graf_world); // and make sure it looks like
assert( pixmap != nil && *pixmap != nil ); // we can use it
assert( (**pixmap).cmpCount == 1 ); // We have a color table index
assert( !PixMap32Bit(pixmap) );
_height = abs((**pixmap).bounds.top - (**pixmap).bounds.bottom);
_width = abs((**pixmap).bounds.right - (**pixmap).bounds.left);
_bytes_per_row = (**pixmap).rowBytes & 0x7fff;
assert( _height > 0 && _height < 10000 ); // Just to play safe
assert( _width > 0 && _width <= _bytes_per_row );
activate_palette(); // Activate palette for the window
}
// Dispose of the offscreen buffer
OffScreenWindow::~OffScreenWindow(void)
{
assert( graf_world != nil );
DisposeGWorld(graf_world);
graf_world = nil;
PaletteHandle window_palette = GetPalette(our_window());
if( window_palette != nil ) // dispose of our palette if was allocated
{
SetPalette(our_window(),nil,FALSE);
DisposePalette(window_palette);
}
pixmap = nil;
_height = _width = _bytes_per_row = 0;
}
// Make sure that the colors of our off-screen
// buffer would be displayed properly (or close enough)
// on screen
void OffScreenWindow::activate_palette(void)
{
CTabHandle window_ctab = (**pixmap).pmTable;
assert( window_ctab != nil && *window_ctab != nil );
PaletteHandle palette = NewPalette((**window_ctab).ctSize,window_ctab,pmTolerant+pmExplicit,0);
assert( palette != nil );
SetPalette(our_window(),palette,TRUE);
do_well( QDError() );
ActivatePalette(our_window());
do_well( QDError() );
}
// Get a bounding rectangle for the window
ScreenRect OffScreenWindow::q_bounds(void) const
{
return (**pixmap).bounds;
}
// Actual drawing - moving the picture from the
// offscreen grafworld to the onscreen one
void OffScreenWindow::draw(void)
{
assert( LockPixels(pixmap) );
Rect& pixmap_rect = (**pixmap).bounds;
CopyBits((const BitMap *)*pixmap, &qd.thePort->portBits, &pixmap_rect,
&our_window()->portRect, /*ditherCopy*/ srcCopy, nil);
UnlockPixels(pixmap);
}